/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package prometheus

import (
	"testing"

	"openfuyao.com/monitoring-service/pkg/client"
)

func TestMakeExpr(t *testing.T) {
	type args struct {
		metric string
		opts   client.QueryOptions
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "Cluster level CPU usage",
			args: args{
				metric: "cluster_cpu_usage",
				opts:   client.QueryOptions{Level: client.LevelCluster},
			},
			want: `sum(rate(node_cpu_seconds_total{mode!="idle", mode!="iowait", ` +
				`mode!="steal"}[5m])) by (cluster)`,
		},

		{
			name: "Node level CPU usage",
			args: args{
				metric: "node_cpu_usage",
				opts: client.QueryOptions{
					Level:    client.LevelNode,
					NodeName: "host-192-168-100-5",
				},
			},
			want: `sum(label_replace(sum(machine_cpu_cores{node=~"host-192-168-100-5"}) by (cluster, node), ` +
				`"instance", "$1", "node", "(.*)")) by (cluster, instance) * (1 - ` +
				`(avg(irate(node_cpu_seconds_total{mode="idle",` +
				`instance=~"host-192-168-100-5"}[5m])) by (cluster, instance)))`,
		},

		{
			name: "Workload (Statefulsets) level CPU usage",
			args: args{
				metric: "workload_cpu_usage",
				opts: client.QueryOptions{
					Level:           client.LevelStatefulset,
					NamespaceName:   "monitoring",
					StatefulsetName: "alertmanager-main",
				},
			},
			want: `sum by (cluster, namespace, pod) (irate(container_cpu_usage_seconds_total{job="kubelet", ` +
				`metrics_path="/metrics/cadvisor", container!="", image!=""}[5m])) * on (cluster, namespace, pod) ` +
				`group_left(owner_kind, owner_name) kube_pod_owner{owner_kind="StatefulSet", ` +
				`owner_name=~"alertmanager-main", ` +
				`job="kube-state-metrics"} * on (cluster, namespace, pod) group_left(node) kube_pod_info{pod=~".*().*", ` +
				`namespace=~"monitoring", job="kube-state-metrics"}`,
		},

		{
			name: "Pod level CPU usage",
			args: args{
				metric: "pod_cpu_usage",
				opts: client.QueryOptions{
					Level:         client.LevelPod,
					NamespaceName: "monitoring",
					PodName:       "alertmanager-main-0",
				},
			},
			want: `sum(irate(container_cpu_usage_seconds_total{pod=~"alertmanager-main-0", namespace=~"monitoring", ` +
				`image!="", job="kubelet", ` +
				`metrics_path="/metrics/cadvisor"}[5m])) by (cluster, namespace, pod, container)`,
		},

		{
			name: "Container level CPU usage",
			args: args{
				metric: "pod_cpu_usage",
				opts: client.QueryOptions{
					Level:         client.LevelContainer,
					NamespaceName: "monitoring",
					PodName:       "alertmanager-main-0",
					ContainerName: "alertmanager",
				},
			},
			want: `sum(irate(container_cpu_usage_seconds_total{namespace=~"monitoring", pod=~"alertmanager-main-0", ` +
				`container=~"alertmanager", image!="", job="kubelet", ` +
				`metrics_path="/metrics/cadvisor"}[5m])) by (cluster, namespace, pod, container)`,
		},

		{
			name: "Kube apiserver QPS by verb and resource",
			args: args{
				metric: "kube_apiserver_qps_by_verb_resource",
				opts: client.QueryOptions{
					Level:     client.LevelControlPlaneComponents,
					Component: client.KubeAPIServer,
					Verb:      "LIST",
					Resource:  "customresourcedefinitions",
				},
			},
			want: `sum(rate(apiserver_request_total{job="apiserver", verb=~"LIST", ` +
				`resource=~"customresourcedefinitions"}[5m])) by (cluster, verb, resource)`,
		},

		{
			name: "ETCD CPU usage",
			args: args{
				metric: "etcd_cpu_usage",
				opts: client.QueryOptions{
					Level:     client.LevelControlPlaneComponents,
					Component: client.ETCD,
					Instance:  "192.168.100.5:2379",
				},
			},
			want: `sum(rate(process_cpu_seconds_total{job="etcd", ` +
				`instance=~"192.168.100.5:2379"}[5m])) by (cluster, instance)`,
		},

		{
			name: "Kube scheduler CPU usage",
			args: args{
				metric: "kube_scheduler_cpu_usage",
				opts: client.QueryOptions{
					Level:     client.LevelControlPlaneComponents,
					Component: client.KubeScheduler,
					Instance:  "192.168.100.5:10259",
				},
			},
			want: `sum(rate(process_cpu_seconds_total{job="kube-scheduler", ` +
				`instance=~"192.168.100.5:10259"}[5m])) by (cluster, instance)`,
		},

		{
			name: "Kube controller manager CPU usage",
			args: args{
				metric: "kube_controller_manager_cpu_usage",
				opts: client.QueryOptions{
					Level:     client.LevelControlPlaneComponents,
					Component: client.KubeControllerManager,
					Instance:  "192.168.100.5:10257",
				},
			},
			want: `sum(rate(process_cpu_seconds_total{job="kube-controller-manager", ` +
				`instance=~"192.168.100.5:10257"}[5m])) by (cluster, instance)`,
		},

		{
			name: "Kubelet CPU usage",
			args: args{
				metric: "kubelet_cpu_usage",
				opts: client.QueryOptions{
					Level:     client.LevelNodeComponents,
					Component: client.Kubelet,
					Instance:  "192.168.100.5:10250",
				},
			},
			want: `sum(rate(process_cpu_seconds_total{job="kubelet", metrics_path="/metrics", ` +
				`instance=~"192.168.100.5:10250"}[5m])) by (cluster, instance)`,
		},

		{
			name: "Kube proxy CPU usage",
			args: args{
				metric: "kube_proxy_cpu_usage",
				opts: client.QueryOptions{
					Level:     client.LevelNodeComponents,
					Component: client.Kubelet,
					Instance:  "host-192-168-100-5",
				},
			},
			want: `sum(rate(process_cpu_seconds_total{job="kube-proxy", ` +
				`instance=~"host-192-168-100-5"}[5m])) by (cluster, instance)`,
		},

		{
			name: "CoreDNS cache size",
			args: args{
				metric: "coredns_cache_size",
				opts: client.QueryOptions{
					Level:     client.LevelAddonsComponents,
					Component: client.CoreDNS,
					Instance:  "172.17.177.104:9153",
				},
			},
			want: `sum(coredns_cache_entries{job="kube-dns", instance=~"172.17.177.104:9153"}) by (cluster, ` +
				`instance, type)`,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := makeExpr(tt.args.metric, tt.args.opts); got != tt.want {
				t.Errorf("makeExpr() = %v, want %v", got, tt.want)
			}
		})
	}
}
